home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
hity wydania
/
Ubuntu 9.10 PL
/
karmelkowy-koliberek-desktop-9.10-i386-PL.iso
/
casper
/
filesystem.squashfs
/
usr
/
bin
/
jockey-gtk
< prev
next >
Wrap
Text File
|
2009-10-25
|
15KB
|
395 lines
#!/usr/bin/python
# (c) 2007 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
'''GTK user interface implementation.'''
import sys, os.path, os
import glib, gtk, gobject, pynotify
import jockey.ui
from jockey.oslib import OSLib
class GtkUI(jockey.ui.AbstractUI):
'''GTK user interface implementation.'''
#
# Implementation of required AbstractUI methods
#
def convert_keybindings(self, str):
'''Keyboard accelerator aware gettext() wrapper.
This optionally converts keyboard accelerators to the appropriate
format for the frontend.
A double underscore ('__') is converted to a real '_'.
'''
# nothing to do for GTK
return str
def ui_init(self):
'''Initialize UI.'''
# load UI
self.widgets = gtk.Builder()
ui_path = '/usr/share/jockey/jockey-gtk.ui'
if not os.path.exists(ui_path):
ui_path = os.path.join(os.path.dirname(__file__), 'jockey-gtk.ui')
self.widgets.add_from_file(ui_path)
self.widgets.connect_signals(self)
self.w('label_license_label').set_label(self.string_license_label)
self.w('linkbutton_licensetext').set_label('(%s)' % self.string_details)
self.w('dialog_licensetext').set_title(self.string_license_dialog_title)
def ui_show_main(self):
'''Show main window.'''
# check $DISPLAY validity, etc.
try:
gtk.init_check()
except RuntimeError:
self.error_msg('Could not initialize GTK: invalid $DISPLAY?')
sys.exit(1)
self.treeview = self.w('treeview_drivers')
self.w('dialog_manager').set_title(self.main_window_title())
# initialize handler treeview (but only do it once)
if not self.treeview.get_columns():
self.treeview.set_headers_visible(False)
# icon
pixbuf_renderer = gtk.CellRendererPixbuf()
col_icon = gtk.TreeViewColumn()
col_icon.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
col_icon.set_expand(False)
col_icon.pack_start(pixbuf_renderer, False)
col_icon.set_attributes(pixbuf_renderer, pixbuf=1)
self.treeview.append_column(col_icon)
# name
text_renderer = gtk.CellRendererText()
col_name = gtk.TreeViewColumn()
col_name.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
col_name.set_expand(True)
col_name.pack_start(text_renderer, True)
col_name.set_attributes(text_renderer, text=2)
self.treeview.append_column(col_name)
self.treeview.grab_focus()
self.update_driver_info_ui(None)
self.update_tree_model()
# show help button?
if not OSLib.inst.ui_help_available(self):
self.w('button_help').hide()
# EDGE is the default, but that centers if there is just one button
self.w('button_box_main').set_layout(gtk.BUTTONBOX_END)
# default height of details scrollwindow is too small
self.w('dialog_manager').set_default_size(-1, 550)
# default vpane size
if len(self.get_displayed_handlers()) < 2:
self.w('vpaned1').set_position(36)
elif len(self.get_displayed_handlers()) < 4:
self.w('vpaned1').set_position(72)
else:
self.w('vpaned1').set_position(100)
# lift the curtain
self.w('dialog_manager').show()
def ui_main_loop(self):
'''Main loop for the user interface.
This should return if the user wants to quit the program, and return
the exit code.
'''
gtk.main()
self.w('dialog_manager').hide()
def error_message(self, title, text):
'''Present an error message box.'''
self.msgbox = gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
buttons=gtk.BUTTONS_CLOSE, message_format=text)
if title:
self.msgbox.set_title(title)
self.msgbox.run()
self.msgbox.destroy()
self.msgbox = None
def confirm_action(self, title, text, subtext=None, action=None):
'''Present a confirmation dialog.
If action is given, it is used as button label instead of the default
'OK'. Return True if the user confirms, False otherwise.
'''
if action:
self.msgbox = gtk.MessageDialog(type=gtk.MESSAGE_QUESTION,
message_format=text)
self.msgbox.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
self.msgbox.add_button(action, gtk.RESPONSE_OK).set_image(
gtk.image_new_from_stock(gtk.STOCK_APPLY,
gtk.ICON_SIZE_BUTTON))
else:
self.msgbox = gtk.MessageDialog(type=gtk.MESSAGE_QUESTION,
message_format=text, buttons=gtk.BUTTONS_OK_CANCEL)
if subtext:
self.msgbox.format_secondary_text(subtext)
if title:
self.msgbox.set_title(title)
ret = self.msgbox.run()
self.msgbox.destroy()
self.msgbox = None
return ret == gtk.RESPONSE_OK
def ui_notification(self, title, text):
'''Present a notification popup.
This should preferably create a tray icon. Clicking on the tray icon or
notification should run the GUI.
'''
pynotify.init('jockey')
trayicon = gtk.status_icon_new_from_icon_name('jockey')
trayicon.connect('activate', lambda widget: self.ui_show_main())
trayicon.set_visible(False)
trayicon.set_tooltip(title)
trayicon.set_visible(True)
self.ui_idle()
# creating the notification immediately causes the bubble to point into
# the void; icon needs to settle first
gobject.timeout_add (500, self.show_notification,
(title, text, trayicon))
def show_notification(self, data):
(title, text, trayicon) = data
notify = pynotify.Notification(title, text, 'jockey')
notify.set_urgency(pynotify.URGENCY_NORMAL)
notify.attach_to_status_icon(trayicon)
notify.set_timeout(10000)
notify.show()
def ui_idle(self):
'''Process pending UI events and return.
This is called while waiting for external processes such as package
installers.
'''
while gtk.events_pending():
gtk.main_iteration(False)
def ui_progress_start(self, title, description, total):
'''Create a progress dialog.'''
self.w('progress').set_fraction(0)
self.w('label_description').set_label(description)
self.w('window_progress').set_title(title)
self.w('window_progress').set_transient_for(self.w('dialog_manager'))
self.w('window_progress').show()
self.cancel_progress = False
def ui_progress_update(self, current, total):
'''Update status of current progress dialog.
current/total specify the number of steps done and total steps to
do, or -1 if it cannot be determined. In this case the dialog should
display an indeterminated progress bar (bouncing back and forth).
This should return True to cancel, and False otherwise.
'''
if current < 0 or total < 0:
self.w('progress').set_pulse_step(0.1)
self.w('progress').pulse()
else:
self.w('progress').set_fraction(float(current)/total)
return self.cancel_progress
def ui_progress_finish(self):
'''Close the current progress dialog.'''
self.w('window_progress').hide()
#
# helper functions
#
def w(self, widget):
'''Shortcut for getting an UI widget from GtkBuilder.'''
return self.widgets.get_object(widget)
def update_tree_model(self):
'''Update treeview to current set of handlers and their states.'''
# handler ID, icon, name
self.model = gtk.ListStore(gobject.TYPE_STRING, gtk.gdk.Pixbuf, gobject.TYPE_STRING)
theme = gtk.icon_theme_get_default()
cur_path = self.treeview.get_cursor()[0]
for h_id in self.get_displayed_handlers():
info = self.get_ui_driver_info(h_id)
if info['needs_reboot']:
pixbuf = theme.load_icon(gtk.STOCK_REFRESH, 16, gtk.ICON_LOOKUP_USE_BUILTIN)
elif info['enabled']:
try:
pixbuf = theme.load_icon('jockey-enabled', 16, 0)
except glib.GError:
pixbuf = theme.load_icon(gtk.STOCK_YES, 16, gtk.ICON_LOOKUP_USE_BUILTIN)
else:
try:
pixbuf = theme.load_icon('jockey-disabled', 16, 0)
except glib.GError:
pixbuf = theme.load_icon(gtk.STOCK_NO, 16, gtk.ICON_LOOKUP_USE_BUILTIN)
iter = self.model.append([h_id, pixbuf, info['name']])
if not cur_path:
cur_path = self.model.get_path(iter)
self.treeview.set_model(self.model)
if cur_path:
self.treeview.set_cursor(cur_path)
self.treeview.expand_all()
self.w('label_heading').set_label('<span weight="bold">%s</span>\n\n%s' %
self.main_window_text())
def update_driver_info_ui(self, handler_id):
'''Update UI elements which show the driver details.
If handler_id is None, then no driver is selected, no information
shown, and the appropriate controls are disabled.
'''
info = self.get_ui_driver_info(handler_id)
self.w('label_drivername').set_label('<b>%s</b>' % info['name'])
self.current_driver_name = info['name']
self.w('textview_description').get_buffer().set_text(info['description'])
if info['certified'] == None:
self.w('image_certification').hide()
elif info['certified']:
self.w('image_certification').show()
self.w('image_certification').set_from_icon_name('jockey-certified', gtk.ICON_SIZE_BUTTON)
else:
self.w('image_certification').show()
self.w('image_certification').set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_BUTTON)
self.w('label_certification').set_label(info['certification_label'])
if info['free'] == None:
self.w('image_license').hide()
self.w('label_license_label').hide()
elif info['free']:
self.w('image_license').show()
self.w('label_license_label').show()
self.w('image_license').set_from_icon_name('jockey-free', gtk.ICON_SIZE_BUTTON)
else:
self.w('image_license').show()
self.w('label_license_label').show()
self.w('image_license').set_from_icon_name('jockey-proprietary',
gtk.ICON_SIZE_BUTTON)
self.w('label_license').set_label(info['license_label'])
if info['license_text']:
self.w('linkbutton_licensetext').show()
self.current_license_text = info['license_text']
else:
self.w('linkbutton_licensetext').hide()
self.current_license_text = None
if info['enabled'] == None:
self.w('image_enabled').hide()
elif info['needs_reboot']:
self.w('image_enabled').show()
self.w('image_enabled').set_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_BUTTON)
elif info['enabled']:
self.w('image_enabled').show()
self.w('image_enabled').set_from_icon_name('jockey-enabled', gtk.ICON_SIZE_BUTTON)
else:
self.w('image_enabled').show()
self.w('image_enabled').set_from_icon_name('jockey-disabled', gtk.ICON_SIZE_BUTTON)
self.w('label_status').set_label(info['status_label'])
if not info['button_toggle_label']:
self.w('button_toggle').set_label(self.string_button_enable)
self.w('button_toggle').set_sensitive(False)
else:
self.w('button_toggle').set_sensitive(True)
self.w('button_toggle').set_label(info['button_toggle_label'])
if info['enabled']:
self.w('button_toggle').set_image(
gtk.image_new_from_icon_name('jockey-disabled', gtk.ICON_SIZE_BUTTON))
else:
self.w('button_toggle').set_image(
gtk.image_new_from_icon_name('jockey-enabled', gtk.ICON_SIZE_BUTTON))
#
# event callbacks
#
def on_quit(self, *args):
gtk.main_quit()
return True
def on_button_help_clicked(self, widget):
OSLib.inst.ui_help(self)
return True
def on_button_toggle_clicked(self, widget):
self.treeview.set_sensitive(False)
if self.set_handler_enable(self.model[self.treeview.get_cursor()[0]][0],
'toggle', False):
self.update_tree_model()
self.treeview.set_sensitive(True)
return True
def on_treeview_drivers_cursor_changed(self, widget):
path = widget.get_cursor()[0]
if path:
h_id = self.model[path][0]
else:
h_id = None
self.update_driver_info_ui(h_id)
return True
def on_progress_cancel(self, *args):
self.cancel_progress = True
return True
def on_linkbutton_licensetext_clicked(self, widget):
self.w('label_license_drivername').set_label('<b>%s</b>' %
self.current_driver_name)
self.w('textview_license_text').get_buffer().set_text(self.current_license_text)
self.w('dialog_licensetext').set_default_size(600, 480)
self.w('dialog_licensetext').run()
self.w('dialog_licensetext').hide()
return True
if __name__ == '__main__':
if not os.environ.get('DISPLAY'):
print >> sys.stderr, 'This program needs a running X session. Please use jockey-text for a command line version of Jockey.'
sys.exit(1)
OSLib.inst = OSLib(client_only=True)
u = GtkUI()
sys.exit(u.run())